
package com.wobaby.util.xml;

import java.util.*;
import org.w3c.dom.*;

public class XMLElement
{

    public XMLElement(Node node)
    {
        m_name = null;
        m_attributes = null;
        m_subElements = null;
        m_text = null;
        m_exactText = null;
        m_name = node.getNodeName();
        NamedNodeMap attributes = node.getAttributes();
        if(attributes != null && attributes.getLength() > 0)
        {
            m_attributes = new HashMap();
            for(int index = 0; index < attributes.getLength(); index++)
            {
                Node attribute = attributes.item(index);
                m_attributes.put(attribute.getNodeName(), attribute.getNodeValue());
            }

        }
        List subElements = new Vector();
        String text = "";
        String exactText = "";
        NodeList childNodes = node.getChildNodes();
        if(childNodes != null && childNodes.getLength() > 0)
        {
            for(int index = 0; index < childNodes.getLength(); index++)
            {
                Node childNode = childNodes.item(index);
                if(childNode.getNodeType() == 1)
                {
                    subElements.add(new XMLElement(childNode));
                    continue;
                }
                if(childNode.getNodeType() != 3 && childNode.getNodeType() != 4)
                    continue;
                String nodeText = childNode.getNodeValue();
                if(nodeText.length() > 0)
                    exactText = exactText + nodeText;
                nodeText = nodeText.trim();
                if(nodeText.length() <= 0)
                    continue;
                if(text.length() > 0)
                    text = text + " ";
                text = text + nodeText;
            }

        }
        if(subElements.size() > 0)
            m_subElements = subElements;
        if(text.length() > 0)
            m_text = text;
        if(exactText.length() > 0)
            m_exactText = exactText;
    }

    public String getName()
    {
        return m_name;
    }

    public Map getAttributes()
    {
        return m_attributes;
    }

    public String getAttribute(String attributeName)
    {
        if(m_attributes != null)
            return (String)m_attributes.get(attributeName);
        else
            return null;
    }

    public List getSubelements()
    {
        return m_subElements;
    }

    public List getSubelements(String elementName)
    {
        if(m_subElements == null)
            return null;
        List returnElements = new Vector();
        Iterator elementIter = m_subElements.iterator();
        do
        {
            if(!elementIter.hasNext())
                break;
            XMLElement element = (XMLElement)elementIter.next();
            if(element.getName().equals(elementName))
                returnElements.add(element);
        } while(true);
        if(returnElements.size() == 0)
            return null;
        else
            return returnElements;
    }

    public List getSubelementsByAttribute(String attrName, String attrValue)
    {
        if(m_subElements == null || attrValue == null)
            return null;
        List returnElements = new Vector();
        Iterator elementIter = m_subElements.iterator();
        do
        {
            if(!elementIter.hasNext())
                break;
            XMLElement element = (XMLElement)elementIter.next();
            if(attrValue.equals(element.getAttribute(attrName)))
                returnElements.add(element);
        } while(true);
        if(returnElements.size() == 0)
            return null;
        else
            return returnElements;
    }

    public XMLElement getSubelementByAttribute(String attrName, String attrValue)
    {
        if(m_subElements == null || attrValue == null)
            return null;
        for(Iterator elementIter = m_subElements.iterator(); elementIter.hasNext();)
        {
            XMLElement element = (XMLElement)elementIter.next();
            if(attrValue.equals(element.getAttribute(attrName)))
                return element;
        }

        return null;
    }

    public XMLElement getSingleSubelement(String elementName)
    {
        List elements = getSubelements(elementName);
        if(elements == null)
            return null;
        if(elements.size() > 1)
            throw new RuntimeException("Expecting a single '" + elementName + "' subelement under a '" + m_name + "' element, but found " + elements.size());
        else
            return (XMLElement)elements.get(0);
    }

    public String getText()
    {
        return m_text;
    }

    public String getText(boolean trimmed)
    {
        if(trimmed)
            return m_text;
        else
            return m_exactText;
    }

    public String toString()
    {
        return toString("");
    }

    private String toString(String indent)
    {
        StringBuilder sb = new StringBuilder();
        sb.append(indent);
        sb.append('<').append(m_name);
        if(m_attributes != null && m_attributes.size() > 0)
        {
            String attr;
            String val;
            for(Iterator attrIter = m_attributes.keySet().iterator(); attrIter.hasNext(); sb.append(' ').append(attr).append("=\"").append(val).append('"'))
            {
                attr = (String)attrIter.next();
                val = (String)m_attributes.get(attr);
            }

        }
        boolean endTag = false;
        if(m_text != null && m_text.length() > 0)
        {
            sb.append(">");
            endTag = true;
            boolean multiLineText = false;
            if(m_text.indexOf('\n') >= 0)
                multiLineText = true;
            if(multiLineText)
                sb.append('\n');
            sb.append(m_text);
            if(multiLineText)
                sb.append('\n');
        }
        if(m_subElements != null && m_subElements.size() > 0)
        {
            if(!endTag)
            {
                sb.append(">\n");
                endTag = true;
            }
            String newIndent = indent + "  ";
            for(int idx = 0; idx < m_subElements.size(); idx++)
            {
                XMLElement elem = (XMLElement)m_subElements.get(idx);
                sb.append(elem.toString(newIndent));
            }

        }
        if(!endTag)
            sb.append("/>\n");
        else
            sb.append(indent).append("</").append(m_name).append(">\n");
        return sb.toString();
    }

    private String m_name;
    private Map m_attributes;
    private List m_subElements;
    private String m_text;
    private String m_exactText;
}